package com.javalab._7thread._3Lock._3JUC._2Condition;

import java.util.LinkedList;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class MyStack {
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    private ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
    private ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
    /**
     * 不能跟wait() notify() notifyAll()混淆
     * await()
     * signal()
     * signalAll()
     */
    private Condition condition = writeLock.newCondition();
    private static final int MAX_SIZE = 5;
    private LinkedList<Integer> list = new LinkedList<>();

    public void push(Integer element) throws InterruptedException {
        try {
            writeLock.lock();
            if (list.size() >= MAX_SIZE) {
                condition.await();
            }
            Thread.sleep(new Random().nextInt(10));
            list.addLast(element);
            System.out.println("push" + list);
            condition.signal();
        } finally {
            writeLock.unlock();
        }
    }

    public Integer pop() throws InterruptedException {
        try {
            writeLock.lock();
            if (list.isEmpty()) {
                condition.await();
            }
            Thread.sleep(new Random().nextInt(1000));
            Integer result = list.removeFirst();
            System.out.println("pop " + list);
            condition.signal();
            return result;
        } finally {
            writeLock.unlock();
        }
    }

    public LinkedList<Integer> list() {
        try {
            readLock.lock();
            return list;
        } finally {
            readLock.unlock();
        }
    }

    public int size() {
        try {
            readLock.lock();
            return list.size();
        } finally {
            readLock.unlock();
        }
    }
}
